package com.sunnada.edu.system.quartz;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Scope;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import com.sunnada.edu.system.pub.dao.PubDao;


/**
 * 描述 spring容器初始化 定时器
 * 
 * @author Session Zhang
 * @created 2016年3月7日 下午5:24:20
 */
@Service
@Scope("singleton")
public class QuartzListener implements ApplicationListener<ContextRefreshedEvent> {
    @Resource
    private Scheduler myScheduler; // SchedulerFactoryBean 由spring创建注入
    @Resource
    private PubDao pubDao;

    /**
     * 描述 执行定时器列表数据
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午2:26:43
     * @throws SchedulerException
     * @throws ClassNotFoundException
     */
    public void init() throws SchedulerException, ClassNotFoundException {
        if (myScheduler != null) {
            List<ScheduleJob> jobList = getAllJob();
            for (ScheduleJob job : jobList) {
                TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
                // 获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
                CronTrigger trigger = (CronTrigger) myScheduler.getTrigger(triggerKey);
                // 不存在，创建一个
                if (null == trigger) {
                    Class t = Class.forName(job.getClassName());
                    JobDetail jobDetail = JobBuilder.newJob(t)
                            .withIdentity(job.getJobName(), job.getJobGroup()).build();
                    jobDetail.getJobDataMap().put("scheduleJob", job);
                    // 表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job
                            .getCronExpression());
                    // 按新的cronExpression表达式构建一个新的trigger
                    trigger = TriggerBuilder.newTrigger()
                            .withIdentity(job.getJobName(), job.getJobGroup())
                            .withSchedule(scheduleBuilder).build();
                    myScheduler.scheduleJob(jobDetail, trigger);
                } else {
                    // Trigger已存在，那么更新相应的定时设置
                    // 表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job
                            .getCronExpression());
                    // 按新的cronExpression表达式重新构建trigger
                    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                            .withSchedule(scheduleBuilder).build();
                    // 按新的trigger重新设置job执行
                    myScheduler.rescheduleJob(triggerKey, trigger);
                }
            }
        }
    }

    /**
     * 描述 暂停任务
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午4:55:34
     * @throws SchedulerException
     */
    public void pauseJob(ScheduleJob scheduleJob) throws SchedulerException {
        if (myScheduler != null) {
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            myScheduler.pauseJob(jobKey);
        }
    }

    /**
     * 描述 立即执行一次任务
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午4:55:34
     * @throws SchedulerException
     */
    public void triggerJob(ScheduleJob scheduleJob) throws SchedulerException {
        if (myScheduler != null) {
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            myScheduler.triggerJob(jobKey);
        }
    }

    /**
     * 描述 恢复任务
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午4:56:36
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void resumeJob(ScheduleJob scheduleJob) throws SchedulerException {
        if (myScheduler != null) {
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            myScheduler.resumeJob(jobKey);
        }
    }

    /**
     * 描述 删除任务
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午4:57:32
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void deleteJob(ScheduleJob scheduleJob) throws SchedulerException {
        if (myScheduler != null) {
            JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            myScheduler.deleteJob(jobKey);
        }
    }

    /**
     * 描述 重新执行任务
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午5:02:14
     * @param scheduleJob
     * @throws SchedulerException
     */
    public void rescheduleJob(ScheduleJob scheduleJob) throws SchedulerException {
        if (myScheduler != null) {
            TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(),
                    scheduleJob.getJobGroup());
            // 获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
            CronTrigger trigger = (CronTrigger) myScheduler.getTrigger(triggerKey);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob
                    .getCronExpression());
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder).build();
            // 按新的trigger重新设置job执行
            myScheduler.rescheduleJob(triggerKey, trigger);
        }
    }

    /**
     * 描述 获取定时器列表数据
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午2:27:56
     * @return
     */
    public List<ScheduleJob> getAllJob() {
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        String sql = "SELECT T.JOBID,T.JOBNAME,T.JOBGROUP,T.CLASSNAME,T.CRON,T.JOBDESC FROM S_CONFIG_QUARTZ  T  WHERE T.JOBSTATUS='1'";
        List<HashMap<String, String>> taskPackages = (List<HashMap<String, String>>) pubDao
                .selectList(sql);
        for (int i = 0; i < taskPackages.size(); i++) {
            HashMap<String, String> map = taskPackages.get(i);
            String jobId = map.get("JOBID");
            String jobName = map.get("JOBNAME");
            String jobGroup = map.get("JOBGROUP");
            String className = map.get("CLASSNAME");
            String jobStatus = map.get("JOBSTATUS");
            String cron = map.get("CRON").trim();
            String desc = map.get("JOBDESC");
            ScheduleJob job = new ScheduleJob();
            job.setJobId(jobId);
            job.setJobName(jobName);
            job.setJobGroup(jobGroup);
            job.setClassName(className);
            job.setJobStatus(jobStatus);
            job.setCronExpression(cron);
            job.setDesc(desc);
            jobList.add(job);
        }
        return jobList;
    }

    /**
     * 描述 spring容器启动时的回调方法
     * 
     * @author Session Zhang
     * @created 2016年3月7日 下午2:58:51
     * @param arg0
     * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        try {
            if (event.getApplicationContext().getParent() == null) {// 保证框中代码只执行一次
                init();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

}
